# -*- coding: UTF-8 -*-
from django.shortcuts import redirect
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.http import HttpResponse

import models

#get_screen_width() by author @ 2014
WIDTHS = [
    (126,    1), (159,    0), (687,     1), (710,   0), (711,   1),
    (727,    0), (733,    1), (879,     0), (1154,  1), (1161,  0),
    (4347,   1), (4447,   2), (7467,    1), (7521,  0), (8369,  1),
    (8426,   0), (9000,   1), (9002,    2), (11021, 1), (12350, 2),
    (12351,  1), (12438,  2), (12442,   0), (19893, 2), (19967, 1),
    (55203,  2), (63743,  1), (64106,   2), (65039, 1), (65059, 0),
    (65131,  2), (65279,  1), (65376,   2), (65500, 1), (65510, 2),
    (120831, 1), (262141, 2), (1114109, 1),
]

def get_screen_width(input_str, width=30, need_truncate=True, tail='.', tail_length=3):
    """
    Get screen width of given string. A SBC case character is caculated as 2, and a DBC case one is caculated as 1.
    """

    def get_char_width(char):
        """
        Return the screen width of a single character given.
        """
        char = ord(char)
        if char == 0xe or char == 0xf:
            return 0

        for num, wid in WIDTHS:
            if char <= num:
                return wid

        return 1

    total_width = 0
    max_width = width - tail_length
    max_trigger = False

    for i in range(0, len(input_str)):
        increase = get_char_width(input_str[i])
        total_width += increase

        if need_truncate:
            if total_width == max_width:
                max_trigger = True
                continue
            elif total_width > max_width:
                if max_trigger:
                    return input_str[0:i-1] + tail*tail_length
                else:
                    return input_str[0:i] + tail*(tail_length-1)

    if need_truncate:
        return input_str
    else:
        return total_width

#page_guide() by author @ 2014/5/30
#redirect to http_referer or another page
def page_guide(request, to='self', page='index'):
    if request.META['HTTP_REFERER'] and to=='referer':
        return redirect(request.META['HTTP_REFERER'])
    elif to=='self':
        return redirect(request.path)
    elif to=='login':
        return redirect('member_operate', action='login')
    else:
        return redirect(page)

#by author @ 2014/6/1
def smart_paginator(input, page=1, num=5, wing_width=5):
    paginator = Paginator(input, num)
    try:
        output = paginator.page(page)
    except PageNotAnInteger:
        #need a better error page
        return HttpResponse("err_read_post_1")
    except EmptyPage:
        #need a better error logic
        return HttpResponse("err_read_post_2")

    #Generate a list for displaying page link in templates
    #Belowing is schematic diagram of page link
    #    OO...OO        X      OO...OO
    #    ~~~~~~~       ~~~     ~~~~~~~
    #   links before link now  links after
    #Normally, width(numbers) of links before/after is equivalent,
    #I call it "wing_width"
    if paginator.num_pages <= (wing_width*2 + 1):
        link_list = paginator.page_range
    else:
        if page_num <= (wing_width +1):
            link_list = paginator.page_range[:(wing_width*2+1)]
        elif page_num >= (paginator.num_pages - wing_width):
            link_list = paginator.page_range[-(wing_width*2+1):]
        else:
            link_list = range((page_num-wing_width), (page_num+wing_width+1))

    return {'output': output, 'link_list': link_list}

#updated by author @ 2014/6/21
def get_permissions(request, obj):
    user_valid = request.user.is_authenticated() and request.user.is_active

    if isinstance(obj, models.Board):
        return get_board_permission(request, obj, user_valid)

    elif isinstance(obj, models.Topic):
        is_author = check_author(request, obj, user_valid)

        if is_author:
            perm_list = get_board_permission(request, obj.board, user_valid)
            perm_list.extend(['read', 'del', 'edit'])
            return perm_list
        else:
            return get_board_permission(request, obj.board, user_valid)

def has_permission(request, obj, perm_type, perm_list=None):
    if perm_list is None:
        return perm_type in get_permissions(request, obj)
    else:
        return perm_type in perm_list

def get_board_permission(request, obj, user_valid):
    if request.user.is_superuser:
        return ['read', 'reply', 'push', 'post', 'del', 'edit']

    if request.user.has_perm(obj.admin_permission.codename):
        return parse_perm(obj.admin_perm)

    if user_valid:
        if obj.restrict:
            if request.user.has_perm(obj.co_permission.codename):
                return parse_perm(obj.user_perm)
            else:
                return []
        else:
            return parse_perm(obj.user_perm)
    else:
        if obj.restrict:
            return []

        return parse_perm(obj.anonymous_perm)

def parse_perm(perm_string):
    perm_list = []
    if perm_string[0] == '1':
        perm_list.append('read')

    if perm_string[1] == '1':
        perm_list.extend(['reply', 'push'])

    if perm_string[2] == '1':
        perm_list.append('post')

    if perm_string[3] == '1':
        perm_list.append('del')

    if perm_string[4] == '1':
        perm_list.append('edit')

    return perm_list

#return true is user is valid and the author of obj,
#otherwise, return false
def check_author(request, obj, user_valid):
    if user_valid:
        return request.user == obj.author
    else:
        return False
